/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Ships;

import Audio.MP3;
import Audio.WAV;
import Engine.Engine;
import Engine.QuadTree;
import Objects.Laser;
import Objects.Missile;
import Objects.MovableObject;
import gleem.linalg.Vec3f;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;
import java.util.TreeMap;

/**
 * Nave.
 * @author Gustavo Buzogany Eboli
 */
public class Ship extends MovableObject {

    protected float power;//
    protected float maxPower;//

    protected ArrayList<Vec3f> turretPos;
    protected ArrayList<Float> turretOrientation;
    protected ArrayList<Boolean> turretFlag;

    protected ArrayList<Vec3f> podPos;
    protected ArrayList<Float> podOrientation;
    protected ArrayList<Boolean> podFlag;

    protected int maxPods;//
    protected int podCount;//
    protected int maxMissile;//
    protected int missileCount;//

    protected TreeMap inventory;

    protected MovableObject target;
    private Vec3f pointsAngle;
    private int laserDelay;
    private int powerDelay;

    private int weaponsPower;
    private int shieldsPower;

    protected MP3 shotSound;

    /*
     * tipos:
     * 1 - x-wing
     * 2 - tie-fighter
     * 3 - battleship
     */

    public Ship(int id, Engine engine, int type)
    {
        super(id, engine);

        File shotFile = new File("laser.mp3");
        shotSound = new MP3(shotFile);

        turretPos           = new ArrayList<Vec3f>();
        turretFlag          = new ArrayList<Boolean>();
        turretOrientation   = new ArrayList<Float>();

        podPos           = new ArrayList<Vec3f>();
        podFlag          = new ArrayList<Boolean>();
        podOrientation   = new ArrayList<Float>();

        switch(type)
        {
            case 1:
                this.r = 2.0f;
                power = 100;
                name = "X-wing";
                modelID = 0;
                maxPods = 2;
                podCount = 0;
                maxMissile = 4;
                missileCount = 0;
                maxPower = 100;

                Vec3f turret = new Vec3f(2.0f, -0.4f, 0);
                Float tOrientation = new Float(0.0f);
                turretPos.add(turret);
                turretFlag.add(true);
                turretOrientation.add(tOrientation);

                turret = new Vec3f(-2.0f, -0.4f, 0);
                tOrientation = new Float(0.0f);
                turretPos.add(turret);
                turretFlag.add(true);
                turretOrientation.add(tOrientation);

                Vec3f pod = new Vec3f(2.0f, -0.4f, 0);
                Float pOrientation = new Float(0.0f);
                podPos.add(pod);
                podFlag.add(true);
                podOrientation.add(pOrientation);

                pod = new Vec3f(-2.0f, -0.4f, 0);
                pOrientation = new Float(0.0f);
                podPos.add(pod);
                podFlag.add(false);
                podOrientation.add(pOrientation);

                maxSpeed = 0.7f;
                isBot = false;
                //invulnerable = true;

                weaponsPower = 50;
                shieldsPower = 50;

                break;
            case 2:
                this.r = 2.0f;
                power = 1000;
                maxPower = 1000;
                name = "Tie Fighter";
                modelID = 5;
                maxPods = 2;
                podCount = 0;
                maxMissile = 2;

                turret = new Vec3f(2.0f, -0.4f, 0);
                tOrientation = new Float(0.0f);
                turretPos.add(turret);
                turretFlag.add(true);
                turretOrientation.add(tOrientation);

                turret = new Vec3f(-2.0f, -0.4f, 0);
                tOrientation = new Float(0.0f);
                turretPos.add(turret);
                turretFlag.add(true);
                turretOrientation.add(tOrientation);

                pod = new Vec3f(2.0f, -0.4f, 0);
                pOrientation = new Float(0.0f);
                podPos.add(pod);
                podFlag.add(true);
                podOrientation.add(pOrientation);

                pod = new Vec3f(-2.0f, -0.4f, 0);
                pOrientation = new Float(0.0f);
                podPos.add(pod);
                podFlag.add(true);
                podOrientation.add(pOrientation);

                weaponsPower = 100;
                shieldsPower = 0;

                maxSpeed = 1.0f;
                isBot = true;
                break;
        }
    }

    public void shootLaser()
    {
        if (laserDelay == 0) {
            if(power > (5*weaponsPower/100))
            {
                new Thread(shotSound).start();
                for (int i = 0; i < turretPos.size(); i++) {
                    if (turretFlag.get(i) == true) {
                        Laser newShot = new Laser(engine.getNextIdentifier(), engine);
                        newShot.setDamage(weaponsPower);
                        newShot.setOrigin(this);
                        newShot.setOrientation(turretOrientation.get(i), turretPos.get(i));
                        newShot.setVisible(true);
                        newShot.setCullingVisible(true);
                        engine.insertMovable(newShot);
                        power -= (int) (5*weaponsPower/100);
                        if(power < 0)
                        {
                            power = 0;
                        }
                    }
                }
            }
            laserDelay = 10;
        }

    }

    public void shootMissile(MovableObject target)
    {
        for(int i = 0; i < turretPos.size(); i++)
        {
            if(turretFlag.get(i) == true)
            {
                Missile newMissile = new Missile(engine.getNextIdentifier(), engine);
                newMissile.setOrigin(this);
                newMissile.setOrientation(podOrientation.get(i), podPos.get(i));
                newMissile.setTarget(target);
                newMissile.setVisible(true);
                newMissile.setCullingVisible(true);
                engine.insertMovable(newMissile);
            }
        }

    }

    private float getAngle(Vec3f pos)
    {
        pointsAngle = pos.minus(this.pos);

        float radAng = (float) ((euler_ang.x() * Math.PI / 180) + Math.PI / 2);
        Vec3f orientationAngle = new Vec3f(((float) Math.cos(radAng)*2), ((float) Math.sin(radAng)*2), 0);

        orientationAngle.normalize();
        pointsAngle.normalize();

        double ang = Math.acos(orientationAngle.dot(pointsAngle))*180/Math.PI;

        double signal = Math.atan2(pointsAngle.x(), pointsAngle.y())-Math.atan2(orientationAngle.x(), orientationAngle.y());
        if(signal > 0)
            ang *= -1;

        return (float) ang;
    }

    public void turnTo(Vec3f pos) {
        int signal = 0;
        if (target.getVisible() == true) {
            float ang = getAngle(pos);
            if (ang < 0) {
                this.setAng_speed(-4.0f, 0, 0);
            } else {
                this.setAng_speed(4.0f, 0, 0);
            }
            if ((ang > 0 && ang < 5.0f) || (ang < 0 && ang > -5.0f)) {
                accelerate(0.3f);
            }
        }
    }

    public void setTarget(MovableObject tgt) {
        this.target = tgt;
    }

    private void increasePower()
    {
        if(power < maxPower && powerDelay == 0)
        {
            power++;
            powerDelay = 7;
        } else
        {
            powerDelay--;
        }
        if(powerDelay < 0)
        {
            powerDelay = 0;
        }
    }

    @Override
    public void update(QuadTree qt) {
        decreaseLaserDelay();
        increasePower();
        speed = speed.addScaled(0.01f, accel);
        if(speed.length() > maxSpeed)
        {
            speed.normalize();
            speed.scale(maxSpeed);
        }
        qt.ObjectMoved(this, pos);


        if (isBot == true) {
            this.turnTo(target.getPos());
            Random rand = new Random();
            if(rand.nextInt(100) <= 10)
            {
                //this.shootLaser();
            }
        }
        
        ang_speed = ang_speed.addScaled(0.01f, ang_accel);
        if (ang_speed.x() > 5.0f) {
            ang_speed.setX(5.0f);
        } else if (ang_speed.x() < -5.0f) {
            ang_speed.setX(-5.0f);
        }

        euler_ang.add(ang_speed);
        if (this.euler_ang.x() > 360) {
            this.euler_ang.setX(this.euler_ang.x() - 360);
        }
        if (this.euler_ang.x() < -360) {
            this.euler_ang.setX(this.euler_ang.x() + 360);
        }
        pos.add(speed);
    }

    private void decreaseLaserDelay() {
        if(laserDelay > 0)
            laserDelay--;
    }

    public float getPower() {
        return power;
    }

    public void setPower(float power) {
        this.power = power;
    }

    public float getPowerPerc() {
        return power/maxPower;
    }

    public float getMaxPower() {
        return maxPower;
    }

    public void setMaxPower(float maxPower) {
        this.maxPower = maxPower;
    }

    public void increaseMaxHealth(int val) {
        health_max += val;
    }

    public int getShieldsPower() {
        return shieldsPower;
    }

    public int getWeaponsPower() {
        return weaponsPower;
    }

    public void increaseMaxPower(int i) {
        maxPower += i;
    }

    public void setShieldsPower(int shieldsPower) {
        this.shieldsPower = shieldsPower;
    }

    public void setWeaponsPower(int weaponsPower) {
        this.weaponsPower = weaponsPower;
    }

    
}
